gtk_widget_activate_action
gtk_widget_activate_default
GtkWidgetActionActivateFunc
-GtkWidgetActionSetStateFunc
-GtkWidgetActionGetStateFunc
gtk_widget_class_install_action
-gtk_widget_class_install_stateful_action
+gtk_widget_class_install_property_action
gtk_widget_class_query_action
gtk_widget_action_enabled_changed
-gtk_widget_action_state_changed
<SUBSECTION Standard>
GTK_WIDGET
--- /dev/null
+/*
+ * Copyright © 2010 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Vincent Untz <vuntz@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gsettings-mapping.h"
+
+static GVariant *
+g_settings_set_mapping_int (const GValue *value,
+ const GVariantType *expected_type)
+{
+ GVariant *variant = NULL;
+ gint64 l;
+
+ if (G_VALUE_HOLDS_INT (value))
+ l = g_value_get_int (value);
+ else if (G_VALUE_HOLDS_INT64 (value))
+ l = g_value_get_int64 (value);
+ else
+ return NULL;
+
+ if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
+ {
+ if (G_MININT16 <= l && l <= G_MAXINT16)
+ variant = g_variant_new_int16 ((gint16) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
+ {
+ if (0 <= l && l <= G_MAXUINT16)
+ variant = g_variant_new_uint16 ((guint16) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
+ {
+ if (G_MININT32 <= l && l <= G_MAXINT32)
+ variant = g_variant_new_int32 ((gint) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
+ {
+ if (0 <= l && l <= G_MAXUINT32)
+ variant = g_variant_new_uint32 ((guint) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
+ {
+ if (G_MININT64 <= l && l <= G_MAXINT64)
+ variant = g_variant_new_int64 ((gint64) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
+ {
+ if (0 <= l && l <= G_MAXUINT64)
+ variant = g_variant_new_uint64 ((guint64) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
+ {
+ if (0 <= l && l <= G_MAXUINT32)
+ variant = g_variant_new_handle ((guint) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
+ variant = g_variant_new_double ((gdouble) l);
+
+ return variant;
+}
+
+static GVariant *
+g_settings_set_mapping_float (const GValue *value,
+ const GVariantType *expected_type)
+{
+ GVariant *variant = NULL;
+ gdouble d;
+ gint64 l;
+
+ if (G_VALUE_HOLDS_DOUBLE (value))
+ d = g_value_get_double (value);
+ else
+ return NULL;
+
+ l = (gint64) d;
+ if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
+ {
+ if (G_MININT16 <= l && l <= G_MAXINT16)
+ variant = g_variant_new_int16 ((gint16) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
+ {
+ if (0 <= l && l <= G_MAXUINT16)
+ variant = g_variant_new_uint16 ((guint16) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
+ {
+ if (G_MININT32 <= l && l <= G_MAXINT32)
+ variant = g_variant_new_int32 ((gint) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
+ {
+ if (0 <= l && l <= G_MAXUINT32)
+ variant = g_variant_new_uint32 ((guint) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
+ {
+ if (G_MININT64 <= l && l <= G_MAXINT64)
+ variant = g_variant_new_int64 ((gint64) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
+ {
+ if (0 <= l && l <= G_MAXUINT64)
+ variant = g_variant_new_uint64 ((guint64) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
+ {
+ if (0 <= l && l <= G_MAXUINT32)
+ variant = g_variant_new_handle ((guint) l);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
+ variant = g_variant_new_double ((gdouble) d);
+
+ return variant;
+}
+static GVariant *
+g_settings_set_mapping_unsigned_int (const GValue *value,
+ const GVariantType *expected_type)
+{
+ GVariant *variant = NULL;
+ guint64 u;
+
+ if (G_VALUE_HOLDS_UINT (value))
+ u = g_value_get_uint (value);
+ else if (G_VALUE_HOLDS_UINT64 (value))
+ u = g_value_get_uint64 (value);
+ else
+ return NULL;
+
+ if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
+ {
+ if (u <= G_MAXINT16)
+ variant = g_variant_new_int16 ((gint16) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
+ {
+ if (u <= G_MAXUINT16)
+ variant = g_variant_new_uint16 ((guint16) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
+ {
+ if (u <= G_MAXINT32)
+ variant = g_variant_new_int32 ((gint) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
+ {
+ if (u <= G_MAXUINT32)
+ variant = g_variant_new_uint32 ((guint) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
+ {
+ if (u <= G_MAXINT64)
+ variant = g_variant_new_int64 ((gint64) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
+ {
+ if (u <= G_MAXUINT64)
+ variant = g_variant_new_uint64 ((guint64) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
+ {
+ if (u <= G_MAXUINT32)
+ variant = g_variant_new_handle ((guint) u);
+ }
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
+ variant = g_variant_new_double ((gdouble) u);
+
+ return variant;
+}
+
+static gboolean
+g_settings_get_mapping_int (GValue *value,
+ GVariant *variant)
+{
+ const GVariantType *type;
+ gint64 l;
+
+ type = g_variant_get_type (variant);
+
+ if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
+ l = g_variant_get_int16 (variant);
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
+ l = g_variant_get_int32 (variant);
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
+ l = g_variant_get_int64 (variant);
+ else
+ return FALSE;
+
+ if (G_VALUE_HOLDS_INT (value))
+ {
+ g_value_set_int (value, l);
+ return (G_MININT32 <= l && l <= G_MAXINT32);
+ }
+ else if (G_VALUE_HOLDS_UINT (value))
+ {
+ g_value_set_uint (value, l);
+ return (0 <= l && l <= G_MAXUINT32);
+ }
+ else if (G_VALUE_HOLDS_INT64 (value))
+ {
+ g_value_set_int64 (value, l);
+ return (G_MININT64 <= l && l <= G_MAXINT64);
+ }
+ else if (G_VALUE_HOLDS_UINT64 (value))
+ {
+ g_value_set_uint64 (value, l);
+ return (0 <= l && l <= G_MAXUINT64);
+ }
+ else if (G_VALUE_HOLDS_DOUBLE (value))
+ {
+ g_value_set_double (value, l);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+g_settings_get_mapping_float (GValue *value,
+ GVariant *variant)
+{
+ const GVariantType *type;
+ gdouble d;
+ gint64 l;
+
+ type = g_variant_get_type (variant);
+
+ if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
+ d = g_variant_get_double (variant);
+ else
+ return FALSE;
+
+ l = (gint64)d;
+ if (G_VALUE_HOLDS_INT (value))
+ {
+ g_value_set_int (value, l);
+ return (G_MININT32 <= l && l <= G_MAXINT32);
+ }
+ else if (G_VALUE_HOLDS_UINT (value))
+ {
+ g_value_set_uint (value, l);
+ return (0 <= l && l <= G_MAXUINT32);
+ }
+ else if (G_VALUE_HOLDS_INT64 (value))
+ {
+ g_value_set_int64 (value, l);
+ return (G_MININT64 <= l && l <= G_MAXINT64);
+ }
+ else if (G_VALUE_HOLDS_UINT64 (value))
+ {
+ g_value_set_uint64 (value, l);
+ return (0 <= l && l <= G_MAXUINT64);
+ }
+ else if (G_VALUE_HOLDS_DOUBLE (value))
+ {
+ g_value_set_double (value, d);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+static gboolean
+g_settings_get_mapping_unsigned_int (GValue *value,
+ GVariant *variant)
+{
+ const GVariantType *type;
+ guint64 u;
+
+ type = g_variant_get_type (variant);
+
+ if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
+ u = g_variant_get_uint16 (variant);
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
+ u = g_variant_get_uint32 (variant);
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
+ u = g_variant_get_uint64 (variant);
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
+ u = g_variant_get_handle (variant);
+ else
+ return FALSE;
+
+ if (G_VALUE_HOLDS_INT (value))
+ {
+ g_value_set_int (value, u);
+ return (u <= G_MAXINT32);
+ }
+ else if (G_VALUE_HOLDS_UINT (value))
+ {
+ g_value_set_uint (value, u);
+ return (u <= G_MAXUINT32);
+ }
+ else if (G_VALUE_HOLDS_INT64 (value))
+ {
+ g_value_set_int64 (value, u);
+ return (u <= G_MAXINT64);
+ }
+ else if (G_VALUE_HOLDS_UINT64 (value))
+ {
+ g_value_set_uint64 (value, u);
+ return (u <= G_MAXUINT64);
+ }
+ else if (G_VALUE_HOLDS_DOUBLE (value))
+ {
+ g_value_set_double (value, u);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+GVariant *
+g_settings_set_mapping (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ gchar *type_string;
+
+ if (G_VALUE_HOLDS_BOOLEAN (value))
+ {
+ if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN))
+ return g_variant_new_boolean (g_value_get_boolean (value));
+ }
+
+ else if (G_VALUE_HOLDS_CHAR (value) ||
+ G_VALUE_HOLDS_UCHAR (value))
+ {
+ if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE))
+ {
+ if (G_VALUE_HOLDS_CHAR (value))
+ return g_variant_new_byte (g_value_get_schar (value));
+ else
+ return g_variant_new_byte (g_value_get_uchar (value));
+ }
+ }
+
+ else if (G_VALUE_HOLDS_INT (value) ||
+ G_VALUE_HOLDS_INT64 (value))
+ return g_settings_set_mapping_int (value, expected_type);
+
+ else if (G_VALUE_HOLDS_DOUBLE (value))
+ return g_settings_set_mapping_float (value, expected_type);
+
+ else if (G_VALUE_HOLDS_UINT (value) ||
+ G_VALUE_HOLDS_UINT64 (value))
+ return g_settings_set_mapping_unsigned_int (value, expected_type);
+
+ else if (G_VALUE_HOLDS_STRING (value))
+ {
+ if (g_value_get_string (value) == NULL)
+ return NULL;
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
+ return g_variant_new_string (g_value_get_string (value));
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTESTRING))
+ return g_variant_new_bytestring (g_value_get_string (value));
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
+ return g_variant_new_object_path (g_value_get_string (value));
+ else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE))
+ return g_variant_new_signature (g_value_get_string (value));
+ }
+
+ else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+ {
+ if (g_value_get_boxed (value) == NULL)
+ return NULL;
+ return g_variant_new_strv ((const gchar **) g_value_get_boxed (value),
+ -1);
+ }
+
+ else if (G_VALUE_HOLDS_ENUM (value))
+ {
+ GEnumValue *enumval;
+ GEnumClass *eclass;
+
+ /* GParamSpecEnum holds a ref on the class so we just peek... */
+ eclass = g_type_class_peek (G_VALUE_TYPE (value));
+ enumval = g_enum_get_value (eclass, g_value_get_enum (value));
+
+ if (enumval)
+ return g_variant_new_string (enumval->value_nick);
+ else
+ return NULL;
+ }
+
+ else if (G_VALUE_HOLDS_FLAGS (value))
+ {
+ GVariantBuilder builder;
+ GFlagsValue *flagsval;
+ GFlagsClass *fclass;
+ guint flags;
+
+ fclass = g_type_class_peek (G_VALUE_TYPE (value));
+ flags = g_value_get_flags (value);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+ while (flags)
+ {
+ flagsval = g_flags_get_first_value (fclass, flags);
+
+ if (flagsval == NULL)
+ {
+ g_variant_builder_clear (&builder);
+ return NULL;
+ }
+
+ g_variant_builder_add (&builder, "s", flagsval->value_nick);
+ flags &= ~flagsval->value;
+ }
+
+ return g_variant_builder_end (&builder);
+ }
+
+ type_string = g_variant_type_dup_string (expected_type);
+ g_critical ("No GSettings bind handler for type \"%s\".", type_string);
+ g_free (type_string);
+
+ return NULL;
+}
+
+gboolean
+g_settings_get_mapping (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
+ {
+ if (!G_VALUE_HOLDS_BOOLEAN (value))
+ return FALSE;
+ g_value_set_boolean (value, g_variant_get_boolean (variant));
+ return TRUE;
+ }
+
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
+ {
+ if (G_VALUE_HOLDS_UCHAR (value))
+ g_value_set_uchar (value, g_variant_get_byte (variant));
+ else if (G_VALUE_HOLDS_CHAR (value))
+ g_value_set_schar (value, (gint8)g_variant_get_byte (variant));
+ else
+ return FALSE;
+ return TRUE;
+ }
+
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64))
+ return g_settings_get_mapping_int (value, variant);
+
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
+ return g_settings_get_mapping_float (value, variant);
+
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
+ return g_settings_get_mapping_unsigned_int (value, variant);
+
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
+ g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
+ {
+ if (G_VALUE_HOLDS_STRING (value))
+ {
+ g_value_set_string (value, g_variant_get_string (variant, NULL));
+ return TRUE;
+ }
+
+ else if (G_VALUE_HOLDS_ENUM (value))
+ {
+ GEnumClass *eclass;
+ GEnumValue *evalue;
+ const gchar *nick;
+
+ /* GParamSpecEnum holds a ref on the class so we just peek... */
+ eclass = g_type_class_peek (G_VALUE_TYPE (value));
+ nick = g_variant_get_string (variant, NULL);
+ evalue = g_enum_get_value_by_nick (eclass, nick);
+
+ if (evalue)
+ {
+ g_value_set_enum (value, evalue->value);
+ return TRUE;
+ }
+
+ g_warning ("Unable to look up enum nick ‘%s’ via GType", nick);
+ return FALSE;
+ }
+ }
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("as")))
+ {
+ if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+ {
+ g_value_take_boxed (value, g_variant_dup_strv (variant, NULL));
+ return TRUE;
+ }
+
+ else if (G_VALUE_HOLDS_FLAGS (value))
+ {
+ GFlagsClass *fclass;
+ GFlagsValue *fvalue;
+ const gchar *nick;
+ GVariantIter iter;
+ guint flags = 0;
+
+ fclass = g_type_class_peek (G_VALUE_TYPE (value));
+
+ g_variant_iter_init (&iter, variant);
+ while (g_variant_iter_next (&iter, "&s", &nick))
+ {
+ fvalue = g_flags_get_value_by_nick (fclass, nick);
+
+ if (fvalue)
+ flags |= fvalue->value;
+
+ else
+ {
+ g_warning ("Unable to lookup flags nick '%s' via GType",
+ nick);
+ return FALSE;
+ }
+ }
+
+ g_value_set_flags (value, flags);
+ return TRUE;
+ }
+ }
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTESTRING))
+ {
+ g_value_set_string (value, g_variant_get_bytestring (variant));
+ return TRUE;
+ }
+
+ g_critical ("No GSettings bind handler for type \"%s\".",
+ g_variant_get_type_string (variant));
+
+ return FALSE;
+}
+
+gboolean
+g_settings_mapping_is_compatible (GType gvalue_type,
+ const GVariantType *variant_type)
+{
+ gboolean ok = FALSE;
+
+ if (gvalue_type == G_TYPE_BOOLEAN)
+ ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN);
+ else if (gvalue_type == G_TYPE_CHAR ||
+ gvalue_type == G_TYPE_UCHAR)
+ ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE);
+ else if (gvalue_type == G_TYPE_INT ||
+ gvalue_type == G_TYPE_UINT ||
+ gvalue_type == G_TYPE_INT64 ||
+ gvalue_type == G_TYPE_UINT64 ||
+ gvalue_type == G_TYPE_DOUBLE)
+ ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_HANDLE) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
+ else if (gvalue_type == G_TYPE_STRING)
+ ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE ("ay")) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
+ g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
+ else if (gvalue_type == G_TYPE_STRV)
+ ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
+ else if (G_TYPE_IS_ENUM (gvalue_type))
+ ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
+ else if (G_TYPE_IS_FLAGS (gvalue_type))
+ ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
+
+ return ok;
+}
--- /dev/null
+/*
+ * Copyright © 2010 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Vincent Untz <vuntz@gnome.org>
+ */
+
+#ifndef __G_SETTINGS_MAPPING_H__
+#define __G_SETTINGS_MAPPING_H__
+
+#include <glib-object.h>
+
+GVariant * g_settings_set_mapping (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data);
+gboolean g_settings_get_mapping (GValue *value,
+ GVariant *variant,
+ gpointer user_data);
+gboolean g_settings_mapping_is_compatible (GType gvalue_type,
+ const GVariantType *variant_type);
+
+#endif /* __G_SETTINGS_MAPPING_H__ */
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkwidget.h"
+#include "gsettings-mapping.h"
#include <string.h>
gtk_action_muxer_primary_accel_changed (muxer, action_name, action_and_target);
}
+static GVariant *
+prop_action_get_state (GtkWidget *widget,
+ GtkWidgetAction *action)
+{
+ GValue value = G_VALUE_INIT;
+ GVariant *result;
+
+ g_value_init (&value, action->pspec->value_type);
+ g_object_get_property (G_OBJECT (widget), action->pspec->name, &value);
+
+ result = g_settings_set_mapping (&value, action->state_type, NULL);
+ g_value_unset (&value);
+
+ return g_variant_ref_sink (result);
+}
+
+static GVariant *
+prop_action_get_state_hint (GtkWidget *widget,
+ GtkWidgetAction *action)
+{
+ if (action->pspec->value_type == G_TYPE_INT)
+ {
+ GParamSpecInt *pspec = (GParamSpecInt *)action->pspec;
+ return g_variant_new ("(ii)", pspec->minimum, pspec->maximum);
+ }
+ else if (action->pspec->value_type == G_TYPE_UINT)
+ {
+ GParamSpecUInt *pspec = (GParamSpecUInt *)action->pspec;
+ return g_variant_new ("(uu)", pspec->minimum, pspec->maximum);
+ }
+ else if (action->pspec->value_type == G_TYPE_FLOAT)
+ {
+ GParamSpecFloat *pspec = (GParamSpecFloat *)action->pspec;
+ return g_variant_new ("(dd)", (double)pspec->minimum, (double)pspec->maximum);
+ }
+ else if (action->pspec->value_type == G_TYPE_DOUBLE)
+ {
+ GParamSpecDouble *pspec = (GParamSpecDouble *)action->pspec;
+ return g_variant_new ("(dd)", pspec->minimum, pspec->maximum);
+ }
+
+ return NULL;
+}
+
+static void
+prop_action_set_state (GtkWidget *widget,
+ GtkWidgetAction *action,
+ GVariant *state)
+{
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, action->pspec->value_type);
+ g_settings_get_mapping (&value, state, NULL);
+
+ g_object_set_property (G_OBJECT (widget), action->pspec->name, &value);
+ g_value_unset (&value);
+}
+
+static void
+prop_action_activate (GtkWidget *widget,
+ GtkWidgetAction *action,
+ GVariant *parameter)
+{
+ if (action->pspec->value_type == G_TYPE_BOOLEAN)
+ {
+ gboolean value;
+
+ g_return_if_fail (parameter == NULL);
+
+ g_object_get (G_OBJECT (widget), action->pspec->name, &value, NULL);
+ value = !value;
+ g_object_set (G_OBJECT (widget), action->pspec->name, value, NULL);
+ }
+ else
+ {
+ g_return_if_fail (parameter != NULL && g_variant_is_of_type (parameter, action->state_type));
+
+ prop_action_set_state (widget, action, parameter);
+ }
+}
+
+static void
+prop_action_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkActionMuxer *muxer = user_data;
+ int i;
+ GtkWidgetAction *action = NULL;
+ GVariant *state;
+
+ g_assert ((GObject *)muxer->widget == object);
+
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ action = g_ptr_array_index (muxer->widget_actions, i);
+ if (action->pspec == pspec)
+ break;
+ action = NULL;
+ }
+
+ g_assert (action != NULL);
+
+ state = prop_action_get_state (muxer->widget, action);
+ gtk_action_muxer_action_state_changed (muxer, action->name, state);
+ g_variant_unref (state);
+}
+
+static void
+prop_actions_connect (GtkActionMuxer *muxer)
+{
+ int i;
+
+ if (!muxer->widget || !muxer->widget_actions)
+ return;
+
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
+ char *detailed;
+
+ if (!action->pspec)
+ continue;
+
+ detailed = g_strconcat ("notify::", action->pspec->name, NULL);
+ g_signal_connect (muxer->widget, detailed,
+ G_CALLBACK (prop_action_notify), muxer);
+ g_free (detailed);
+ }
+}
+
+static void
+prop_actions_disconnect (GtkActionMuxer *muxer)
+{
+ if (muxer->widget)
+ g_signal_handlers_disconnect_by_func (muxer->widget,
+ prop_action_notify, muxer);
+}
+
static gboolean
gtk_action_muxer_query_action (GActionGroup *action_group,
const gchar *action_name,
if (state)
*state = NULL;
- if (action->get_state)
+ if (action->pspec)
{
- GVariant *s;
-
- s = g_variant_ref_sink (action->get_state (muxer->widget, action->name));
-
if (state)
- *state = g_variant_ref (s);
-
- g_variant_unref (s);
+ *state = prop_action_get_state (muxer->widget, action);
+ if (state_hint)
+ *state_hint = prop_action_get_state_hint (muxer->widget, action);
}
return TRUE;
GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
if (strcmp (action->name, action_name) == 0)
{
- action->activate (muxer->widget, action->name, parameter);
+ if (action->activate)
+ action->activate (muxer->widget, action->name, parameter);
+ else if (action->pspec)
+ prop_action_activate (muxer->widget, action, parameter);
return;
}
GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
if (strcmp (action->name, action_name) == 0)
{
- if (action->set_state)
- action->set_state (muxer->widget, action->name, state);
+ if (action->pspec)
+ prop_action_set_state (muxer->widget, action, state);
return;
}
{
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
+ prop_actions_disconnect (muxer);
+
if (muxer->parent)
{
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
->dispose (object);
}
+static void
+gtk_action_muxer_constructed (GObject *object)
+{
+ GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
+
+ prop_actions_connect (muxer);
+
+ G_OBJECT_CLASS (gtk_action_muxer_parent_class)->constructed (object);
+}
+
static void
gtk_action_muxer_get_property (GObject *object,
guint property_id,
{
class->get_property = gtk_action_muxer_get_property;
class->set_property = gtk_action_muxer_set_property;
+ class->constructed = gtk_action_muxer_constructed;
class->finalize = gtk_action_muxer_finalize;
class->dispose = gtk_action_muxer_dispose;
typedef struct {
char *name;
-
GType owner;
- GVariantType *parameter_type;
- GVariantType *state_type;
+ const GVariantType *parameter_type;
GtkWidgetActionActivateFunc activate;
- GtkWidgetActionSetStateFunc set_state;
- GtkWidgetActionGetStateFunc get_state;
+
+ const GVariantType *state_type;
+ GParamSpec *pspec;
} GtkWidgetAction;
typedef struct _GtkActionMuxer GtkActionMuxer;
static void gtk_text_activate_misc_insert_emoji (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
-static void gtk_text_activate_misc_toggle_visibility (GtkWidget *widget,
- const char *action_name,
- GVariant *parameter);
-
-static void gtk_text_set_misc_toggle_visibility (GtkWidget *widget,
- const char *action_name,
- GVariant *state);
-static GVariant *gtk_text_get_misc_toggle_visibility (GtkWidget *widget,
- const char *action_name);
/* GtkTextContent implementation
*/
gtk_text_activate_selection_select_all);
gtk_widget_class_install_action (widget_class, "misc.insert-emoji", NULL,
gtk_text_activate_misc_insert_emoji);
- gtk_widget_class_install_stateful_action (widget_class, "misc.toggle-visibility", NULL,
- gtk_text_activate_misc_toggle_visibility,
- "b",
- gtk_text_set_misc_toggle_visibility,
- gtk_text_get_misc_toggle_visibility);
+ gtk_widget_class_install_property_action (widget_class,
+ "misc.toggle-visibility",
+ "visibility");
}
static void
gtk_text_recompute (self);
gtk_text_update_clipboard_actions (self);
- gtk_widget_action_state_changed (GTK_WIDGET (self), "misc.toggle-visibility",
- g_variant_new_boolean (visible));
}
}
hide_selection_bubble (self);
}
-static void
-gtk_text_activate_misc_toggle_visibility (GtkWidget *widget,
- const char *action_name,
- GVariant *parameter)
-{
- GtkText *self = GTK_TEXT (widget);
- gtk_text_set_visibility (self, !gtk_text_get_visibility (self));
-}
-
-static GVariant *
-gtk_text_get_misc_toggle_visibility (GtkWidget *widget,
- const char *action_name)
-{
- GtkText *self = GTK_TEXT (widget);
- DisplayMode mode = gtk_text_get_display_mode (self);
-
- return g_variant_new_boolean (mode == DISPLAY_NORMAL);
-}
-
-static void
-gtk_text_set_misc_toggle_visibility (GtkWidget *widget,
- const char *action_name,
- GVariant *state)
-{
- GtkText *self = GTK_TEXT (widget);
- gboolean visible = g_variant_get_boolean (state);
- gtk_text_set_visibility (self, visible);
-}
-
static void
gtk_text_update_clipboard_actions (GtkText *self)
{
return TRUE;
}
+static void
+gtk_widget_class_add_action (GtkWidgetClass *widget_class,
+ GtkWidgetAction *action)
+{
+ GtkWidgetClassPrivate *priv = widget_class->priv;
+
+ if (priv->actions == NULL)
+ priv->actions = g_ptr_array_new ();
+ else if (GTK_IS_WIDGET_CLASS (&widget_class->parent_class))
+ {
+ GtkWidgetClass *parent_class = GTK_WIDGET_CLASS (&widget_class->parent_class);
+ GtkWidgetClassPrivate *parent_priv = parent_class->priv;
+ GPtrArray *parent_actions = parent_priv->actions;
+
+ if (priv->actions == parent_actions)
+ {
+ int i;
+
+ priv->actions = g_ptr_array_new ();
+ for (i = 0; i < parent_actions->len; i++)
+ g_ptr_array_add (priv->actions, g_ptr_array_index (parent_actions, i));
+ }
+ }
+
+ GTK_NOTE(ACTIONS, g_message ("%sClass: Adding %s action\n",
+ g_type_name (G_TYPE_FROM_CLASS (widget_class)),
+ action->name));
+
+ g_ptr_array_add (priv->actions, action);
+}
+
/*
* gtk_widget_class_install_action:
* @widget_class: a #GtkWidgetClass
const char *parameter_type,
GtkWidgetActionActivateFunc activate)
{
- gtk_widget_class_install_stateful_action (widget_class, action_name,
- parameter_type, activate,
- NULL, NULL, NULL);
+ GtkWidgetAction *action;
+
+ action = g_new0 (GtkWidgetAction, 1);
+ action->owner = G_TYPE_FROM_CLASS (widget_class);
+ action->name = g_strdup (action_name);
+ if (parameter_type)
+ action->parameter_type = g_variant_type_new (parameter_type);
+ else
+ action->parameter_type = NULL;
+ action->activate = activate;
+
+ gtk_widget_class_add_action (widget_class, action);
+}
+
+static const GVariantType *
+determine_type (GParamSpec *pspec)
+{
+ if (G_TYPE_IS_ENUM (pspec->value_type))
+ return G_VARIANT_TYPE_STRING;
+
+ switch (pspec->value_type)
+ {
+ case G_TYPE_BOOLEAN:
+ return G_VARIANT_TYPE_BOOLEAN;
+
+ case G_TYPE_INT:
+ return G_VARIANT_TYPE_INT32;
+
+ case G_TYPE_UINT:
+ return G_VARIANT_TYPE_UINT32;
+
+ case G_TYPE_DOUBLE:
+ case G_TYPE_FLOAT:
+ return G_VARIANT_TYPE_DOUBLE;
+
+ case G_TYPE_STRING:
+ return G_VARIANT_TYPE_STRING;
+
+ default:
+ g_critical ("Unable to use gtk_widget_class_install_property_action with property '%s::%s' of type '%s'",
+ g_type_name (pspec->owner_type), pspec->name, g_type_name (pspec->value_type));
+ return NULL;
+ }
}
-/*
- * gtk_widget_class_install_stateful_action:
- * @widget_class: a #GtkWidgetClass
- * @action_name: a prefixed action name, such as "clipboard.paste"
- * @parameter_type: (allow-none): the parameter type, or %NULL
- * @activate: callback to use when the action is activated
- * @state_type: (allow-none): the state type, or %NULL
- * @set_state: (allow-none): callback to use when the action state
- is set, or %NULL for stateless actions
- * @get_state: (allow-none): callback to use when the action state
- is queried, or %NULL for stateless actions
- *
- * This should be called at class initialization time to specify
- * actions to be added for all instances of this class.
- *
- * Actions installed in this way can be simple or stateful.
- * See the #GAction documentation for more information.
- */
void
-gtk_widget_class_install_stateful_action (GtkWidgetClass *widget_class,
- const char *action_name,
- const char *parameter_type,
- GtkWidgetActionActivateFunc activate,
- const char *state_type,
- GtkWidgetActionSetStateFunc set_state,
- GtkWidgetActionGetStateFunc get_state)
+gtk_widget_class_install_property_action (GtkWidgetClass *widget_class,
+ const char *action_name,
+ const char *property_name)
{
- GtkWidgetClassPrivate *priv = widget_class->priv;
+ GParamSpec *pspec;
GtkWidgetAction *action;
g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
- if (priv->actions == NULL)
- priv->actions = g_ptr_array_new ();
- else if (GTK_IS_WIDGET_CLASS (&widget_class->parent_class))
- {
- GtkWidgetClass *parent_class = GTK_WIDGET_CLASS (&widget_class->parent_class);
- GtkWidgetClassPrivate *parent_priv = parent_class->priv;
- GPtrArray *parent_actions = parent_priv->actions;
+ pspec = g_object_class_find_property (G_OBJECT_CLASS (widget_class), property_name);
- if (priv->actions == parent_actions)
- {
- int i;
+ if (pspec == NULL)
+ {
+ g_critical ("Attempted to use non-existent property '%s::%s' for dgtk_widget_class_install_property_action",
+ g_type_name (G_TYPE_FROM_CLASS (widget_class)), property_name);
+ return;
+ }
- priv->actions = g_ptr_array_new ();
- for (i = 0; i < parent_actions->len; i++)
- g_ptr_array_add (priv->actions, g_ptr_array_index (parent_actions, i));
- }
+ if (~pspec->flags & G_PARAM_READABLE || ~pspec->flags & G_PARAM_WRITABLE || pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+ {
+ g_critical ("Property '%s::%s' used with gtk_widget_class_install_property_action must be readable, writable, and not construct-only",
+ g_type_name (G_TYPE_FROM_CLASS (widget_class)), property_name);
+ return;
}
action = g_new0 (GtkWidgetAction, 1);
action->owner = G_TYPE_FROM_CLASS (widget_class);
action->name = g_strdup (action_name);
- action->parameter_type = parameter_type ? g_variant_type_new (parameter_type) : NULL;
- action->activate = activate;
- action->state_type = state_type ? g_variant_type_new (state_type) : NULL;
- action->set_state = set_state;
- action->get_state = get_state;
-
- GTK_NOTE(ACTIONS,
- g_message ("%sClass: Adding %s action\n",
- g_type_name (G_TYPE_FROM_CLASS (widget_class)),
- action_name));
+ action->pspec = pspec;
+ action->state_type = determine_type (action->pspec);
+ if (action->pspec->value_type == G_TYPE_BOOLEAN)
+ action->parameter_type = NULL;
+ else
+ action->parameter_type = action->state_type;
+ action->activate = NULL;
- g_ptr_array_add (priv->actions, action);
+ gtk_widget_class_add_action (widget_class, action);
}
/**
gtk_action_muxer_action_enabled_changed (muxer, action_name, enabled);
}
-/**
- * gtk_widget_action_state_changed:
- * @widget: a #GtkWidget
- * @action_name: action name, such as "clipboard.paste"
- * @state: the new state
- *
- * Notify when an action installed with
- * gtk_widget_class_install_stateful_action() changes
- * its state.
- */
-void
-gtk_widget_action_state_changed (GtkWidget *widget,
- const char *action_name,
- GVariant *state)
-{
- GtkActionMuxer *muxer;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- muxer = _gtk_widget_get_action_muxer (widget, TRUE);
- gtk_action_muxer_action_state_changed (muxer, action_name, state);
-}
-
/**
* gtk_widget_class_query_action:
* @widget_class: a #GtkWidgetClass
const char *action_name,
GVariant *parameter);
-/**
- * GtkWidgetActionGetStateFunc:
- * @widget: the widget to which the action belongs
- * @action_name: the action name
- *
- * The type of the callback functions used to query the state
- * of stateful actions installed with gtk_widget_class_install_action().
- *
- * See the #GAction documentation for more details about the
- * meaning of these properties.
- */
-typedef GVariant * (* GtkWidgetActionGetStateFunc) (GtkWidget *widget,
- const char *action_name);
-
-/**
- * GtkWidgetActionSetStateFunc:
- * @widget: the widget to which the action belongs
- * @action_name: the action name
- * @state: the new state
- *
- * The type of the callback functions used to change the
- * state of actions installed with gtk_widget_class_install_action().
- *
- * The @state must match the @state_type of the action.
- *
- * This callback is used when the action state is
- * changed via the #GActionGroup API.
- */
-typedef void (*GtkWidgetActionSetStateFunc) (GtkWidget *widget,
- const char *action_name,
- GVariant *state);
-
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_install_action (GtkWidgetClass *widget_class,
const char *action_name,
GtkWidgetActionActivateFunc activate);
GDK_AVAILABLE_IN_ALL
-void gtk_widget_class_install_stateful_action (GtkWidgetClass *widget_class,
- const char *action_name,
- const char *parameter_type,
- GtkWidgetActionActivateFunc activate,
- const char *state_type,
- GtkWidgetActionSetStateFunc set_state,
- GtkWidgetActionGetStateFunc get_state);
+void gtk_widget_class_install_property_action (GtkWidgetClass *widget_class,
+ const char *action_name,
+ const char *property_name);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_class_query_action (GtkWidgetClass *widget_class,
void gtk_widget_action_enabled_changed (GtkWidget *widget,
const char *action_name,
gboolean enabled);
-GDK_AVAILABLE_IN_ALL
-void gtk_widget_action_state_changed (GtkWidget *widget,
- const char *action_name,
- GVariant *state);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidget, g_object_unref)
'fallback-c89.c',
'fnmatch.c',
'tools/gdkpixbufutils.c',
+ 'gsettings-mapping.c',
'gtkactionhelper.c',
'gtkactionmuxer.c',
'gtkactionobservable.c',